package redisClient

import (
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/Unknwon/goconfig"
	"github.com/go-redis/redis"
)

var rdb *redis.Client

func logInit() {
	logFile, err := os.OpenFile("./go.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		fmt.Println("open log file failed, err:", err)
		return
	}
	log.SetOutput(logFile)
	log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
}

// 初始化连接
func InitClient(host string, port string, pwd string, db int) (err error) {
	rdb = redis.NewClient(&redis.Options{
		Addr:     host + ":" + port,
		Password: pwd, // no password set
		DB:       db,  // use default DB
	})
	// logInit()
	_, err = rdb.Ping().Result()
	if err != nil {
		log.Fatalf("Redis Connect Error!,Details:%v", err)
	}
	// fmt.Println("ok")
	return nil
}

// set
func RedisSet(key string, value interface{}, expire time.Duration) bool {
	err := rdb.Set(key, value, expire).Err()
	if err != nil {
		log.Printf("RedisSet Error! key: %s,Details:%v", key, err)
		return false
	}
	return true
}

// get
func RedisGet(key string) string {
	value, err := rdb.Get(key).Result()
	if err != nil {
		log.Printf("RedisGet Error! key: %s,Details:%v", key, err)
		return ""
	}

	return value
}

// 创建一个消费者组,同时如果没有消息流也会被创建
func RedisCreateGroup(stream string, group string, flag string) (err error) {
	resultCmd := rdb.XGroupCreateMkStream(stream, group, flag)
	err = resultCmd.Err()
	if err != nil {
		if !strings.Contains(resultCmd.String(), "BUSYGROUP") {
			log.Fatalf("create Group Error! Details:%v", err)
		}
	}
	return nil
}

func RedisXPending(stream string, group string, start string, end string, count int64, consumer string) []redis.XPendingExt {
	resultCmd := rdb.XPendingExt(&redis.XPendingExtArgs{
		Stream:   stream,
		Group:    group,
		Start:    start,
		End:      end,
		Count:    count,
		Consumer: consumer,
	})
	err := resultCmd.Err()
	if err != nil {
		log.Printf("XPending Error! Details:%v", err)
		return []redis.XPendingExt{}
	}
	return resultCmd.Val()
}

func RedisXRange(stream string, start string, end string, count int64) []redis.XMessage {
	resultCmd := rdb.XRangeN(stream, start, end, count)
	err := resultCmd.Err()
	if err != nil {
		log.Printf("XPending Error! Details:%v", err)
		return []redis.XMessage{}
	}
	return resultCmd.Val()
}

func RedisKeys(pattern string) []string {
	resultCmd := rdb.Keys(pattern)
	err := resultCmd.Err()
	if err != nil {
		log.Printf("Keys Error! Details:%v", err)
		return []string{}
	}
	return resultCmd.Val()
}

func RedisAckGroup(stream string, group string, ids ...string) int64 {
	resultCmd := rdb.XAck(stream, group, ids...)
	err := resultCmd.Err()
	if err != nil {
		// log.Printf("XAck Error! Details:%v", err)
		return 0
	}
	return resultCmd.Val()
}

func RedisReadGroup(streams []string, group string, consumer string, count int64, block time.Duration) []redis.XStream {
	resultCmd := rdb.XReadGroup(&redis.XReadGroupArgs{
		Group:    group,
		Count:    count,
		Block:    block,
		Streams:  streams,
		Consumer: consumer,
	})
	err := resultCmd.Err()
	if err != nil {
		// log.Printf("XReadGroup Error! Details:%v", err)
		return []redis.XStream{}
	}
	return resultCmd.Val()
}

// 消息流中添加一个信息
func RedisAddStream(stream string, value map[string]interface{}) string {
	resultCmd := rdb.XAdd(&redis.XAddArgs{
		Stream: stream,
		ID:     "",
		Values: value,
	})
	err := resultCmd.Err()
	if err != nil {
		log.Printf("ADD STREAM Error! Details:%v", err)
		return ""
	}
	return resultCmd.Val()
}

func main() {
	var err error
	conf, err := goconfig.LoadConfigFile("../../onlineJudge.conf")
	if err != nil {
		log.Fatal("ReadConfigure:", err)
	}
	host, err := conf.GetValue("REDIS", "REDIS_HOST")
	port, err := conf.GetValue("REDIS", "REDIS_PORT")
	pwd, err := conf.GetValue("REDIS", "REDIS_PWD")
	db, err := conf.Int("REDIS", "REDIS_DATABASE")
	InitClient(host, port, pwd, db)
	// stream, err := conf.GetValue("REDIS", "REDIS_STREAM")
	// if err != nil {
	// 	log.Fatal("ReadConfigure STREAM:", err)
	// }
	// group, err := conf.GetValue("REDIS", "REDIS_GROUP")
	// if err != nil {
	// 	log.Fatal("ReadConfigure GROUP:", err)
	// }
	// res := RedisSet("456", "456 fda gawr", 10*time.Second)
	// print(res)
	res := RedisGet("456")
	print(res)
}
